package com.cloudkinto.service.platform.qoo10.impl;

import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.RabbitQueueConstant;
import com.cloudkinto.common.RedisKeyConstants;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.utils.CsvUtils;
import com.cloudkinto.common.utils.Qoo10Utils;
import com.cloudkinto.common.utils.RakutenUtil;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.dao.*;
import com.cloudkinto.dto.platform.PlatOrderUpdateTimeDto;
import com.cloudkinto.entity.*;
import com.cloudkinto.enumType.common.CountryEnum;
import com.cloudkinto.enumType.operate.OperateTypeEnum;
import com.cloudkinto.service.consumer.vo.StockToPlatformConsumerReq;
import com.cloudkinto.service.consumer.vo.markShip.Qoo10MarkShipConsumerReq;
import com.cloudkinto.service.consumer.vo.order.PlatformOrderCancelReq;
import com.cloudkinto.service.consumer.vo.order.UpdateInventoryLessReq;
import com.cloudkinto.service.consumer.vo.orderSyncRecord.PlatformOrderSyncRecordReq;
import com.cloudkinto.service.consumer.vo.qoo10.Qoo10ClaimInfoConsumerReq;
import com.cloudkinto.service.consumer.vo.qoo10.Qoo10ConsumerReq;
import com.cloudkinto.service.consumer.vo.rakuten.ItemUpdateConsumerReq;
import com.cloudkinto.service.consumer.vo.rakuten.RakutenOrderUpdateConReq;
import com.cloudkinto.service.mail.vo.SendMailConsumerReq;
import com.cloudkinto.service.order.PlatformOrderCopyService;
import com.cloudkinto.service.platform.PlatformOrderService;
import com.cloudkinto.service.platform.PlatformProductService;
import com.cloudkinto.service.platform.qoo10.PlatformOrderQoo10Service;
import com.cloudkinto.service.platform.qoo10.vo.*;
import com.cloudkinto.service.platform.qoo10.vo.good.GoodsInventoryInfoEntity;
import com.cloudkinto.service.platform.qoo10.vo.good.Item;
import com.cloudkinto.service.platform.qoo10.vo.good.ResultObject;
import com.cloudkinto.service.platform.sync.vo.SyncRecordItemReq;
import com.cloudkinto.service.platform.vo.AsyncFinishConsumerReq;
import com.cloudkinto.service.platform.vo.AsyncUpdateConsumerReq;
import com.cloudkinto.service.platform.vo.StockToPlatformRecordVo;
import com.cloudkinto.service.platform.vo.qoo10.InventoryQoo10Req;
import com.cloudkinto.service.platform.vo.rakuten.PlatformProductSyncReq;
import com.cloudkinto.vo.stock.PlatformSkuStockDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author zhangyy
 * @since 2020-08-13
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)//事务回滚
@RequiredArgsConstructor
public class PlatformOrderQoo10ServiceImpl extends ServiceImpl<PlatformOrderDao, PlatformOrderDo> implements PlatformOrderQoo10Service {
    private final PlatformOrderDao dao;
    private final PlatformStoreDao platformStoreDao;
    private final RabbitTemplate rabbitTemplate;
    protected final RedisTemplate redisTemplate;
    private final PlatformOrderDao platformOrderDao;
    private final PlatformOrderService platformOrderService;
    private final PlatformOrderProductDao platformOrderProductDao;
    private final PlatformProductService platformProductService;
    @Value("${gbc.customer}")
    private String customer;
    private final PlatformOrderCopyService platformOrderCopyService;
    private final AsyncJobDao asyncJobDao;
    private final ProductStockDao productStockDao;
    @Value("${gbc.exportPath.omsFilePath}")
    private String omsFilePath;
    @Value("${gbc.uploadPath.omsFileUrl}")
    private String omsFileUrl;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;
    private final PlatformOrderSyncRecordDao platformOrderSyncRecordDao;



    @Override
    public String updateQoo10OrdersHistory(Qoo10ConsumerReq req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return ("店铺对应平台Token未绑定");
        }
        Double time = redisTemplate.opsForZSet().score(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_ + customer, storeDo.getId());
        if (time == null) {
            req.setSearchStartDate(DateUtils.passingDateYear(new Date(), -1));
        } else {
            req.setSearchStartDate(new Date(time.longValue()));
        }
        req.setSearchEndDate(DateUtils.passingDateHour(req.getSearchStartDate(), 12));
        long day = DateUtil.betweenDay(req.getSearchEndDate(), new Date(), true);
        if (day < 14) {
            return ("时间间隔不能小于14天");
        }
        //记录上次同步结束时间， 每次 同步 12小时数据
        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_+ customer, storeDo.getId(), req.getSearchEndDate().getTime() - 1000);
        String accessToken = this.getQoo10Token(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_ + customer, req.getStoreId(), req.getSearchStartDate().getTime());
            return "accessToken 获取失败";
        }
        Set<String> parents = StaticDict.Qoo10_ShippingStatus.getParents();
        List<OrderQoo10Entity> orderQoo10Dos = new ArrayList<>();
        for (String shippingStatus : parents) {
            if (req.getType() == 1 && !shippingStatus.equals("5")) {
                continue;
            }
            String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ShippingBasic.GetShippingInfo_v2" +
                    "&ShippingStat=" + shippingStatus +
                    "&search_condition=" + req.getSearchCondition() +
                    "&key=" + accessToken +
                    "&search_Sdate=" + DateUtils.dateFormatToString(req.getSearchStartDate(), "yyyyMMddHHmmss") +
                    "&search_Edate=" + DateUtils.dateFormatToString(req.getSearchEndDate(), "yyyyMMddHHmmss");
            String body = Qoo10Utils.okHttpRequestGet(url);
            if (StringUtils.isBlank(body)) {
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_ + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                return "Qoo10同步订单连接超时";
            }
            JSONObject object = JSONObject.parseObject(body);
            if (object == null) {
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_ + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                return "Qoo10同步订单失败,JSON body null";
            }
            String ErrorCode = object.getString("ErrorCode");
            String ErrorMsg = object.getString("ErrorMsg");
            if (StringUtils.isNotBlank(ErrorCode)) {
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_ + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                return "Qoo10同步订单失败：" + ErrorCode + "(" + ErrorMsg + ")";
            }
            String ResultObject = JSONObject.parseObject(body).getString("ResultObject");
            if (StringUtils.isBlank(ResultObject)) {
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10_History_ + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                return "Qoo10同步订单失败,待测试解析失败返回值:" + body;
            }
            List<OrderQoo10Entity> list = JSON.parseArray(ResultObject, OrderQoo10Entity.class);
            orderQoo10Dos.addAll(list);
        }

        //要插入的
        List<PlatformOrderCopyDo> platInertList = new ArrayList<>();
        Map<Integer, List<OrderQoo10Entity>> entityMap = orderQoo10Dos.stream().collect(Collectors.groupingBy(OrderQoo10Entity::getOrderNo));
        for (Integer orderNo : entityMap.keySet()) {
            List<OrderQoo10Entity> orderQoo10Entities = entityMap.get(orderNo);
            PlatformOrderCopyDo copyDo = new PlatformOrderCopyDo();
            copyDo.setCompanyId(storeDo.getCompanyId());
            copyDo.setStoreId(storeDo.getId());
            copyDo.setPlatformOrderNo(String.valueOf(orderNo));
            copyDo.setOrderTime(orderQoo10Entities.get(0).getOrderDate());
            copyDo.setPlatformCode(storeDo.getPlatformCode());
            copyDo.setOrderMsg(JSONArray.toJSONString(orderQoo10Entities));
            platInertList.add(copyDo);
        }
        platformOrderCopyService.batchInsert(platInertList);
        return null;
    }



    @Override
    public void platOrderQoo10Sync() {
        List<PlatformStoreDo> storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, "qoo10")
                .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
//        Set<String> parents = StaticDict.Qoo10_ShippingStatus.getParents();
        Map<Long, Long> storeRecordIdMap = new HashMap<>();
        for (PlatformStoreDo storeDo : storeDoList) {
            PlatformOrderSyncRecordDo recordDo = new PlatformOrderSyncRecordDo(storeDo.getPlatformCode(), storeDo.getId(), 1, 0, 0, new Date(), null, storeDo.getCompanyId());
            platformOrderSyncRecordDao.insert(recordDo);
            storeRecordIdMap.put(storeDo.getId(), recordDo.getId());
        }
        for (PlatformStoreDo platformStoreDo : storeDoList) {
            Long syncRecordId = storeRecordIdMap.get(platformStoreDo.getId());
            if (syncRecordId == null) {
                continue;
            }
//            for (String parent : parents) {
            Qoo10ConsumerReq consumerReq = new Qoo10ConsumerReq(platformStoreDo.getId(), null, null, "1", 0, syncRecordId);
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Sync_Qoo10, JSON.toJSONString(consumerReq));
//            }
        }
    }

    public String getQoo10Token(PlatformStoreDo storeDo) {
        String qoo10Token = (String) redisTemplate.opsForValue().get(RedisKeyConstants.Qoo10ACCESSTOKEN_STORE + storeDo.getId());
        if (qoo10Token != null) {
            return qoo10Token;
        }
        if (storeDo.getAppSecret() == null) {
            return null;
        }
        qoo10Token = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
        if (StringUtils.isBlank(qoo10Token)) {
            return null;
        }
        //qoo10token 的过期时间不给。不知道具体失效时间，暂定3分钟
        redisTemplate.opsForValue().set(RedisKeyConstants.Qoo10ACCESSTOKEN_STORE + storeDo.getId(), qoo10Token, 180, TimeUnit.SECONDS);
        return qoo10Token;
    }

    private static final Pattern DATE_TIME_RANGE_PATTERN =
            Pattern.compile("^(\\d{4}-\\d{2}-\\d{2})\\s+(\\d{2}:\\d{2})~(\\d{2}:\\d{2})$");
    private static final Pattern TIME_RANGE_PATTERN =
            Pattern.compile("^(\\d{2}:\\d{2})~(\\d{2}:\\d{2})$");
    private static final Pattern DATE_PATTERN =
            Pattern.compile("^(\\d{4}-\\d{2}-\\d{2})$");

    @Override
    public String updateQoo10Orders(Qoo10ConsumerReq req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return ("店铺对应平台Token未绑定");
        }
        boolean flag = req.getType() == 0;
        if (!flag && req.getType() == 1) {
            long l = DateUtil.betweenDay(req.getSearchStartDate(), req.getSearchEndDate(), true);
            if (l > 30) {
                return "qoo10店铺:" + storeDo.getStoreName() + "每次最多同步30天数据";
            }
        }
        LocalTime now = LocalTime.now();
        int hour = now.getHour();
        int min = now.getMinute();
        if (flag) {
            Double time = redisTemplate.opsForZSet().score(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, storeDo.getId());
            long currency = System.currentTimeMillis();
            if (!(time == null || (currency - time) >= 60 * 5 * 1000)) {
//                return "qoo10同步订单频率过快(5分钟同步一次)";
            }
            //无上次同步时间 或者 上次同步时间在10分钟之前
            redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, storeDo.getId(), currency - 10 * 1000);
            if (hour == 11 && min >= 40) {
                req.setSearchStartDate(DateUtils.passingDate(new Date(), -3));
            }
            else {
                if (time == null) {
                    req.setSearchStartDate(DateUtils.passingDateHour(new Date(), -4));
                } else {
                    req.setSearchStartDate(new Date(time.longValue() - 60 * 1000 * 21));
                }
            }
            req.setSearchEndDate(new Date(currency));
            long l = DateUtil.betweenDay(req.getSearchStartDate(), req.getSearchEndDate(), true);
            if (l > 7) {
                req.setSearchStartDate(DateUtils.passingDate(new Date(), -7));
            }
        }
        //告诉他正在处理
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_SyncRecord_Update, JSON.toJSONString(new PlatformOrderSyncRecordReq(req.getSyncId(), 1, new Date(), req.getSearchStartDate(), req.getSearchEndDate())));
        //{"ErrorCode":-90000,"ErrorMsg":"Invalid Access"}
        String accessToken = this.getQoo10Token(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            if (flag) {
                redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, req.getStoreId(), req.getSearchStartDate().getTime());
            }
            return "accessToken 获取失败";
        }
        List<OrderQoo10Entity> orderQoo10Dos = new ArrayList<>();

        if (StringUtils.isNotBlank(req.getPlatformOrderNo())) {
            Qoo10ApiRes orderByOrderNo = this.getOrderByOrderNo(req.getPlatformOrderNo(), storeDo.getId());
            if (orderByOrderNo.getCode() == 200 && orderByOrderNo.getData() != null) {
                orderQoo10Dos.addAll(orderByOrderNo.getData());
            }
        } else {
            Set<String> parents = StaticDict.Qoo10_ShippingStatus.getParents();
            for (String shippingStatus : parents) {
                if (req.getType() == 1 && !shippingStatus.equals("5")) {
                    continue;
                }
                String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ShippingBasic.GetShippingInfo_v2" +
                        "&ShippingStat=" + shippingStatus +
                        "&search_condition=" + req.getSearchCondition() +
                        "&key=" + accessToken +
                        "&search_Sdate=" + DateUtils.dateFormatToString(req.getSearchStartDate(), "yyyyMMddHHmmss") +
                        "&search_Edate=" + DateUtils.dateFormatToString(req.getSearchEndDate(), "yyyyMMddHHmmss");
                log.info("Qoo10 店铺："+ storeDo.getStoreCode() +" 同步订单请求:\r\n" + url);
                String body = Qoo10Utils.okHttpRequestGet(url);
                if (!(hour == 11 && min >= 40)) {
                    log.info("Qoo10 店铺：" + storeDo.getStoreCode() + " 同步订单返回:\r\n" + body);
                }
                //{
                //  "ResultObject": [],
                //  "ResultCode": 0,
                //  "ResultMsg": "SUCCESS"
                //}
//        {
//            "ErrorCode": -90001,
//                "ErrorMsg": "存在しないAPIです。"
//        }
                if (StringUtils.isBlank(body)) {
                    if (flag) {
                        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                    }
                    return "Qoo10同步订单连接超时";
                }
                JSONObject object = JSONObject.parseObject(body);
                if (object == null) {
                    if (flag) {
                        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                    }
                    return "Qoo10同步订单失败,JSON body null";
                }
                String ErrorCode = object.getString("ErrorCode");
                String ErrorMsg = object.getString("ErrorMsg");
                if (StringUtils.isNotBlank(ErrorCode)) {
                    if (flag) {
                        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                    }
                    return "Qoo10同步订单失败：" + ErrorCode + "(" + ErrorMsg + ")";
                }
                String ResultObject = JSONObject.parseObject(body).getString("ResultObject");
                if (StringUtils.isBlank(ResultObject)) {
                    if (flag) {
                        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_Qoo10 + customer, req.getStoreId(), req.getSearchStartDate().getTime());
                    }
                    return "Qoo10同步订单失败,待测试解析失败返回值:" + body;
                }
                List<OrderQoo10Entity> list = JSON.parseArray(ResultObject, OrderQoo10Entity.class);
                orderQoo10Dos.addAll(list);
            }
        }
        //获取这些订单的 最近更新时间
        List<String> platformOrders = orderQoo10Dos.stream().map(i -> String.valueOf(i.getOrderNo())).distinct().collect(Collectors.toList());
        Map<String, PlatOrderUpdateTimeDto> orderMap = new HashMap<>();
        if (!platformOrders.isEmpty()) {
            List<List<String>> partition = ListUtil.partition(platformOrders, 5000);
            for (List<String> list : partition) {
                List<PlatOrderUpdateTimeDto> platOrder = platformOrderDao.getPlatOrder(list, storeDo.getId(), "qoo10");
                orderMap.putAll(platOrder.stream().collect(Collectors.toMap(PlatOrderUpdateTimeDto::getPlatformOrderNo,
                        i -> i, (i1, i2) -> i1)));
            }
        }
        //要插入的
        List<PlatformOrderDo> platInertList = new ArrayList<>();
        List<PlatformOrderDo> platUpdateList = new ArrayList<>();
        //子表插入的
        List<PlatformOrderProductDo> platInsetItems = new ArrayList<>();
        List<PlatformOrderProductDo> platUpdateItems = new ArrayList<>();
        Map<Integer, List<OrderQoo10Entity>> entityMap = orderQoo10Dos.stream().collect(Collectors.groupingBy(OrderQoo10Entity::getOrderNo));
        List<SetSellerCheckYNTimeReq> setSellerCheckYNReqList = new ArrayList<>();
        for (Integer orderNo : entityMap.keySet()) {
            List<OrderQoo10Entity> orderQoo10Entities = entityMap.get(orderNo);
            PlatOrderUpdateTimeDto oldUpdateTime = orderMap.get(String.valueOf(orderNo));
            if (oldUpdateTime != null &&
                    (StaticDict.Platform_Order_Status.Three.getValue().equals(oldUpdateTime.getStatus()) || StaticDict.Platform_Order_Status.Four.getValue().equals(oldUpdateTime.getStatus()))) {
                //本地订单是已完成状态
                continue;
            }
            PlatformOrderDo orderDo = new PlatformOrderDo();
            orderDo.setReserveFlag(0);
            orderDo.setCompanyId(storeDo.getCompanyId());
            orderDo.setTenantId(storeDo.getTenantId());
            orderDo.setPlatformCode(storeDo.getPlatformCode());
            orderDo.setStoreId(storeDo.getId());
            orderDo.setSite(storeDo.getSite());
            orderDo.setOrderTime(orderQoo10Entities.get(0).getOrderDate());
            orderDo.setPayTime(orderQoo10Entities.get(0).getPaymentDate());
            orderDo.setLastUpdateDate(null);
            orderDo.setPlatformOrderNo(String.valueOf(orderNo));
            orderDo.setRemark(null);
            //解析   2025-07-17 19:00~21:00 或者  19:00~21:00 或者 2025-07-17
            if (StringUtils.isNotBlank(orderQoo10Entities.get(0).getHopeDate())) {
                try {
                    Matcher dateTimeRangeMatcher = DATE_TIME_RANGE_PATTERN.matcher(orderQoo10Entities.get(0).getHopeDate());
                    Matcher dateTimeRangeMatcher2 = TIME_RANGE_PATTERN.matcher(orderQoo10Entities.get(0).getHopeDate());
                    Matcher dateTimeRangeMatcher3 = DATE_PATTERN.matcher(orderQoo10Entities.get(0).getHopeDate());
                    if (dateTimeRangeMatcher.matches()) {
                        orderDo.setDeliveryDate(dateTimeRangeMatcher.group(1));
                        orderDo.setDeliveryTimeName(dateTimeRangeMatcher.group(2).replace(":00", "") + "-" + dateTimeRangeMatcher.group(3).replace(":00", ""));
                    } else if (dateTimeRangeMatcher2.matches()) {
                        orderDo.setDeliveryTimeName(dateTimeRangeMatcher2.group(1).replace(":00", "") + "-" + dateTimeRangeMatcher2.group(2).replace(":00", ""));
                    } else if (dateTimeRangeMatcher3.matches()) {
                        orderDo.setDeliveryDate(dateTimeRangeMatcher3.group(1));
                    }
                    else {
                        orderDo.setDeliveryDate(orderQoo10Entities.get(0).getHopeDate());
                    }
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
            orderDo.setBasketId(String.valueOf(orderQoo10Entities.get(0).getPackNo()));
            List<String> shipStatusList = orderQoo10Entities.stream().map(OrderQoo10Entity::getShippingStatus).distinct().collect(Collectors.toList());
            Integer status = StaticDict.Platform_Order_Status.Zero.getValue();
            if (shipStatusList.size() == 1 && shipStatusList.contains("Delivered(5)")) {
                status = StaticDict.Platform_Order_Status.Three.getValue();
//                orderDo.setMarkShipmentStatus(4);
            } else if (CollUtil.isEmpty(shipStatusList)) {
                status = StaticDict.Platform_Order_Status.Four.getValue();
            }
            if (oldUpdateTime == null) {
                orderDo.setStatus(status);
            } else if (!StaticDict.Platform_Order_Status.Zero.getValue().equals(status)) {
                orderDo.setStatus(status);
            }
            if (oldUpdateTime != null && oldUpdateTime.getPayTime() != null && (orderDo.getStatus() == null || orderDo.getStatus() == oldUpdateTime.getStatus())) {
                continue;
            }
            orderDo.setShipTime(orderQoo10Entities.get(0).getDeliveredDate());
            orderDo.setReceiver(orderQoo10Entities.get(0).getReceiver());
            orderDo.setTelephone(orderQoo10Entities.get(0).getReceiverTel());
            if (StringUtils.isBlank(orderDo.getTelephone()) || "+81--".equals(orderDo.getTelephone())) {
                orderDo.setTelephone(orderQoo10Entities.get(0).getReceiverMobile());
            }
            if (StringUtils.isNotBlank(orderDo.getTelephone())) {
                orderDo.setTelephone(orderDo.getTelephone().replaceAll("\\+81-", ""));
            }
            orderDo.setCountryRegionCode(orderQoo10Entities.get(0).getShippingCountry());
            orderDo.setProvinceCode(null);
            orderDo.setProvinceName(null);
            orderDo.setPostcode(orderQoo10Entities.get(0).getZipCode());
            orderDo.setHouseNum("");
//            orderDo.setCityCode(orderQoo10Entities.get(0).getAddr2());//1266-6
            String addr1 = orderQoo10Entities.get(0).getAddr1();//// 東京都町田市山崎町
//            if (StringUtils.isBlank(addr1)) {
            addr1 = orderQoo10Entities.get(0).getShippingAddr();
//            }
            if (StringUtils.isNotBlank(addr1)) {//  京都府京都市北区鷹峯上ノ町 11番地1アルフィナード鷹峯204号室
                int index1 = addr1.indexOf("県");
                int index2 = addr1.indexOf("都");
                int index3 = addr1.indexOf("道");
                int index4 = addr1.indexOf("府");
                List<Integer> indexList = new ArrayList<>();
                if (index1 != -1) {
                    indexList.add(index1);
                }
                if (index2 != -1) {
                    indexList.add(index2);
                }
                if (index3 != -1) {
                    indexList.add(index3);
                }
                if (index4 != -1) {
                    indexList.add(index4);
                }
                Collections.sort(indexList);
                if (indexList.isEmpty()) {
                    orderDo.setDistrict(addr1.substring(0, 3));
                    addr1 = addr1.substring(3);
                } else {
                    int firstIndex = indexList.get(0) < 2 ? indexList.get(0) + 1 : indexList.get(0);
                    orderDo.setDistrict(addr1.substring(0, firstIndex + 1));
                    addr1 = addr1.substring(firstIndex + 1);
                }
            }
            if (StringUtils.isNotBlank(addr1) && addr1.length() > 2) {
                int index1 = addr1.indexOf("村");
                int index2 = addr1.indexOf("市");
                int index3 = addr1.indexOf("区");
                int index4 = addr1.indexOf("郡");
                int index5 = addr1.indexOf("町");
                List<Integer> indexList = new ArrayList<>();
                if (index1 != -1) {
                    indexList.add(index1);
                }
                if (index2 != -1) {
                    indexList.add(index2);
                }
                if (index3 != -1) {
                    indexList.add(index3);
                }
                if (index4 != -1) {
                    indexList.add(index4);
                }
                if (index5 != -1) {
                    indexList.add(index5);
                }
                Collections.sort(indexList);
                if (indexList.isEmpty()) {
                    orderDo.setCityCode(addr1.substring(0, 3));
                    orderDo.setAddressOne(addr1.substring(3));
                } else {
                    int firstIndex = indexList.get(0) < 1 ? indexList.get(0) + 1 : indexList.get(0);
                    orderDo.setCityCode(addr1.substring(0, firstIndex + 1));
                    orderDo.setAddressOne(addr1.substring(firstIndex + 1));
                }
            } else {
                orderDo.setAddressOne(addr1);
            }
            //发件人信息
            orderDo.setBuyerName(orderQoo10Entities.get(0).getBuyer());
            orderDo.setBuyerEmail(orderQoo10Entities.get(0).getBuyerEmail());
            float amount = 0f;
            for (OrderQoo10Entity orderQoo10Entity : orderQoo10Entities) {
                amount += orderQoo10Entity.getOrderPrice() * orderQoo10Entity.getOrderQty();
            }
            orderDo.setTotalAmount(BigDecimal.valueOf(amount));
            orderDo.setCurrencyCode(CountryEnum.JP.getCurrency());

            orderDo.setCoupon(new BigDecimal(orderQoo10Entities.get(0).getDiscount() == null ? 0 : orderQoo10Entities.get(0).getDiscount()));
            orderDo.setReqPrice(new BigDecimal(orderQoo10Entities.get(0).getTotal() == null ? 0 : orderQoo10Entities.get(0).getTotal()));
            orderDo.setPostagePrice(new BigDecimal(orderQoo10Entities.get(0).getShippingRate() == null ? 0 : orderQoo10Entities.get(0).getShippingRate()));
            //商品信息
            StringBuilder builder = new StringBuilder();
            for (OrderQoo10Entity itemEntity : orderQoo10Entities) {
                PlatformOrderProductDo platItem = new PlatformOrderProductDo();
                platItem.setPlatformOrderNo(String.valueOf(orderNo));
                platItem.setPlatformSku(StringUtils.isBlank(itemEntity.getOptionCode()) ? itemEntity.getSellerItemCode() : itemEntity.getOptionCode());
                platItem.setPlatformProductName(itemEntity.getItemTitle());
                platItem.setPlatformQty(itemEntity.getOrderQty());
                platItem.setSkuType(1);
                platItem.setItemAmount(BigDecimal.valueOf(itemEntity.getOrderPrice()));
                platItem.setCurrencyCode(CountryEnum.JP.getCurrency());
                if (builder.length() > 0) {
                    builder.append(";");
                }
                builder.append(platItem.getPlatformSku()).append("*").append(platItem.getPlatformQty());
                if (oldUpdateTime != null) {
                    platItem.setOrderId(oldUpdateTime.getId());
                    platUpdateItems.add(platItem);
                } else {
                    platInsetItems.add(platItem);
                }
            }
            if (builder.length() > 100) {
                builder.delete(100, builder.length());
            }
            orderDo.setPlatformSku(builder.toString());
            if (oldUpdateTime != null) {
                orderDo.setId(oldUpdateTime.getId());
                platUpdateList.add(orderDo);
                //如果 是未付款 -> 已付款 且是待处理状态
                if ((orderDo.getStatus() == null || Objects.equals(orderDo.getStatus(), StaticDict.Platform_Order_Status.Zero.getValue()))  && oldUpdateTime.getPayTime() == null && orderDo.getPayTime() != null) {
                    //周日顺延
                    setSellerCheckYNReqList.add(new SetSellerCheckYNTimeReq(orderDo.getPlatformOrderNo(),  orderDo.getPayTime()));
                }
            } else {
                //设置发运时间
                platInertList.add(orderDo);
                //周日顺延
                setSellerCheckYNReqList.add(new SetSellerCheckYNTimeReq(orderDo.getPlatformOrderNo(),  orderDo.getPayTime()));
            }
        }

        if (!platInertList.isEmpty()) {
            platformOrderService.matchSystemSku(platInsetItems, storeDo.getId(), storeDo.getCompanyId(), storeDo.getTenantId());
            Map<String, List<PlatformOrderProductDo>> skuMap = platInsetItems.stream().filter(i -> StringUtils.isNotBlank(i.getSku())).collect(Collectors.groupingBy(PlatformOrderProductDo::getPlatformOrderNo));
            List<PlatformOrderDo> insertList = platInertList.stream().filter(i -> skuMap.containsKey(i.getPlatformOrderNo())).collect(Collectors.toList());
            for (PlatformOrderDo orderDo : insertList) {
                if (skuMap.get(orderDo.getPlatformOrderNo()) == null) {
                    continue;
                }
                boolean exception = false;
                StringBuilder builder = new StringBuilder();
                for (PlatformOrderProductDo productDo : skuMap.get(orderDo.getPlatformOrderNo())) {
                    if (StringUtils.isNotBlank(builder.toString())) {
                        builder.append(";");
                    }
                    builder.append(productDo.getSku()).append("*").append(productDo.getQty());
                    if ("Q10-freight".equals(productDo.getSku())) {
                        exception = true;
                    }
                }
                if (builder.length() > 100) {
                    builder.delete(100, builder.length());
                }
                orderDo.setSku(builder.toString());
                if (exception && !StaticDict.Platform_Order_Status.Three.getValue().equals(orderDo.getStatus())
                        && !StaticDict.Platform_Order_Status.Four.getValue().equals(orderDo.getStatus())) {
                    orderDo.setStatus(StaticDict.Platform_Order_Status.Five.getValue());
                    orderDo.setExceptionCause("客付运费");
                }
            }
            platformOrderDao.insertPlatformOrder(platInertList);
            for (PlatformOrderDo orderDo : platInertList) {
                //去赋值 orderId
                platInsetItems.stream().filter(i -> i.getPlatformOrderNo().equals(orderDo.getPlatformOrderNo())).forEach(item -> item.setOrderId(orderDo.getId()));
            }
        }
        //插入子表
        if (!platInsetItems.isEmpty()) {
            platformOrderProductDao.insertPlatformOrderItems(platInsetItems);
        }
        if (flag) {
            //每四次自动同步 同步一次
            Object o = redisTemplate.opsForValue().
                    get(RedisKeyConstants.orderSyncTimeCountSet_Qoo10 + storeDo.getId() + "_" + customer + "_" + DateUtils.dateFormatToString(new Date()));
            if (o == null || Integer.parseInt(o.toString()) % 12 == 0 || (hour == 11 && min >= 40)) {
                int timeCount = o == null ? 0 : Integer.parseInt(o.toString()) + 1;
                redisTemplate.opsForValue().set(RedisKeyConstants.orderSyncTimeCountSet_Qoo10 + storeDo.getId() + "_" + customer + "_" + DateUtils.dateFormatToString(new Date()), timeCount, 6 * 60 * 60, TimeUnit.SECONDS);
                //获取近 3 - 10天 未发货的订单 未付款
                List<PlatformOrderDo> orderDos = platformOrderDao.selectList(new LambdaQueryWrapper<PlatformOrderDo>()
                        .select(PlatformOrderDo::getId, PlatformOrderDo::getPlatformOrderNo, PlatformOrderDo::getOrderTime)
                        .eq(PlatformOrderDo::getStoreId, storeDo.getId())
                        .in(PlatformOrderDo::getStatus, StaticDict.Platform_Order_Status.Zero.getValue(), StaticDict.Platform_Order_Status.Five.getValue())
                        .ge(PlatformOrderDo::getOrderTime, DateUtil.offsetDay(new Date(), -31))
//                        .le(PlatformOrderDo::getOrderTime, DateUtil.offsetHour(new Date(), -4))
                        .orderByAsc(PlatformOrderDo::getOrderTime));
                if (!orderDos.isEmpty()) {
                    orderDos.stream().filter(i -> i.getPayTime() == null).forEach(orderDo -> {
                        Qoo10ConsumerReq orderConsumerReq = new Qoo10ConsumerReq(storeDo.getId(), null, null, "1", 2, orderDo.getPlatformOrderNo(), null);
                        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Sync_Qoo10, JSON.toJSONString(orderConsumerReq));
                    });
                }
            }
        }

        if (!platUpdateList.isEmpty()) {
            //再交给rabbitMq 去更新子表
            for (PlatformOrderDo orderDo : platUpdateList) {
                List<PlatformOrderDo> array = new ArrayList<>(Collections.singletonList(orderDo));
                List<PlatformOrderProductDo> collect = platUpdateItems.stream().filter(i -> Objects.equals(orderDo.getId(), i.getOrderId())).collect(Collectors.toList());
                rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Qoo10_Update, JSON.toJSONString(new RakutenOrderUpdateConReq(array, collect, storeDo.getId(), storeDo.getCompanyId(), storeDo.getTenantId())));
            }
        }
        List<SyncRecordItemReq> items = platInertList.stream().map(i -> new SyncRecordItemReq(i.getId(), i.getPlatformOrderNo(), storeDo.getId(), storeDo.getCompanyId())).collect(Collectors.toList());
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_SyncRecord_Update, JSON.toJSONString(new PlatformOrderSyncRecordReq(req.getSyncId(), 2, new Date(), null, null, items.size(), items)));
        if (flag) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.StockToPlatform_CreateStockToPlatformAfterSync, storeDo.getId()+"");
        }

        // 指定発送予定日
        List<List<SetSellerCheckYNTimeReq>> partition = ListUtil.partition(setSellerCheckYNReqList, 500);
        partition.forEach(i -> {
//            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Qoo10_SetSellerCheckYN, JSON.toJSONString(new SetCheckYnConsumerReq(i, storeDo)));
        });
        return null;
    }

    /**
     * 计算发货日期（考虑周末顺延）
     * @param orderDate 起始日期（如订单确认日）
     * @param prepareDays 发货准备天数
     * @return 最终发货日期
     */
    public LocalDate calculateDeliveryDate(Date orderDate, int prepareDays) {
        // 参数校验
        if (orderDate == null) {
            return null;
        }
        if (prepareDays < 0) {
            return null;
        }

        LocalDate currentDate = DateUtils.convert(orderDate);
        int remainingDays = prepareDays;

        // 逐天计算，跳过周末
        while (remainingDays > 0) {
            currentDate = currentDate.plusDays(1);
            DayOfWeek dayOfWeek = currentDate.getDayOfWeek();

            // 如果不是周六和周日，才计入准备天数
            if (dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY) {
                remainingDays--;
            }
        }

        return currentDate;
    }


    @Override
    public void platOrderClaimQoo10Sync() {
        List<PlatformStoreDo> storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, "qoo10")
                .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
        for (PlatformStoreDo platformStoreDo : storeDoList) {
            for (int i = 1; i <= 16; i++) {
                Qoo10ClaimInfoConsumerReq claimInfoConsumerReq = new Qoo10ClaimInfoConsumerReq(platformStoreDo, i + "", null, null, "3");
                rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Sync_Qoo10_Claim, JSON.toJSONString(claimInfoConsumerReq));
//                this.getClaimInfo(claimInfoConsumerReq);
            }
//            Qoo10ClaimInfoConsumerReq claimInfoConsumerReq = new Qoo10ClaimInfoConsumerReq(platformStoreDo.getId(), null, null, "3");
//            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformStore_Sync_Qoo10_Claim, JSON.toJSONString(claimInfoConsumerReq));
        }
    }


    @Override
    public String getClaimInfo(Qoo10ClaimInfoConsumerReq req) {
        PlatformStoreDo storeDo = req.getStoreDo();
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return ("店铺对应平台Token未绑定");
        }
        Double time = redisTemplate.opsForZSet().score(RedisKeyConstants.orderSyncTimeSet_ClaimInfo_Qoo10 + req.getClaimStat() + "_" + customer, storeDo.getId());
        long currency = System.currentTimeMillis();
        if (!(time == null || (currency - time) >= 60 * 5 * 1000)) {
//                return "qoo10同步订单频率过快(5分钟同步一次)";
        }
        //无上次同步时间 或者 上次同步时间在10分钟之前
        if (time == null) {
            req.setSearchStartDate(DateUtils.passingDate(new Date(), -30));
        } else {
            req.setSearchStartDate(new Date(time.longValue()));
        }
        req.setSearchEndDate(new Date(currency));
        long l = DateUtil.betweenDay(req.getSearchStartDate(), req.getSearchEndDate(), true);
        if (l > 90) {
            req.setSearchStartDate(DateUtils.passingDate(new Date(), -30));
        }
        String accessToken = this.getQoo10Token(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            return "accessToken 获取失败";
        }
        //	search_condition 照会条件 1：注文日 2：クレーム要求日 3：キャンセル/払い戻し完了日
        String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ShippingBasic.GetClaimInfo_V3" +
                "&key=" + accessToken +
                "&ClaimStat=" + req.getClaimStat() +
                "&search_condition=" + "3" +
                "&search_Sdate=" + DateUtils.dateFormatToString(req.getSearchStartDate(), "yyyyMMddHHmmss") +
                "&search_Edate=" + DateUtils.dateFormatToString(req.getSearchEndDate(), "yyyyMMddHHmmss");
        String body = Qoo10Utils.okHttpRequestGet(url);
        if (StringUtils.isBlank(body)) {
            return "Qoo10同步claim订单连接超时";
        }
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return "Qoo10同步claim订单失败,JSON body null";
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            return "Qoo10同步claim订单失败：" + ErrorCode + "(" + ErrorMsg + ")";
        }
        String ResultObject = JSONObject.parseObject(body).getString("ResultObject");
        String ResultMsg = JSONObject.parseObject(body).getString("ResultMsg");
        if (StringUtils.isBlank(ResultObject)) {
            return "Qoo10同步claim订单失败:" + ResultMsg;
        }
        JSONArray array = JSONArray.parseArray(ResultObject);
        List<String> orderNos = new ArrayList<>();
        for (int i = 0; i < array.size(); i++) {
            orderNos.add(array.getJSONObject(i).getString("orderNo"));
        }
        if (!orderNos.isEmpty()) {
            List<Object> platformOrderIds = dao.selectObjs(new LambdaQueryWrapper<PlatformOrderDo>()
                    .select(PlatformOrderDo::getId)
                    .in(PlatformOrderDo::getStatus, Arrays.asList(StaticDict.Platform_Order_Status.Zero.getValue(), StaticDict.Platform_Order_Status.Two.getValue(), StaticDict.Platform_Order_Status.Five.getValue()))
                    .in(PlatformOrderDo::getPlatformOrderNo, orderNos)
                    .eq(PlatformOrderDo::getStoreId, storeDo.getId())
                    .eq(PlatformOrderDo::getCompanyId, storeDo.getCompanyId())
                    .ge(PlatformOrderDo::getOrderTime, DateUtils.dateFormatToString(DateUtils.passingDate(new Date(), -30))));
            if (platformOrderIds.isEmpty()) {
                return null;
            }
            platformOrderService.update(new LambdaUpdateWrapper<PlatformOrderDo>()
                    .eq(PlatformOrderDo::getPlatformCode, StaticDict.Store_PlatformCode.Qoo10.getValue())
                    .eq(PlatformOrderDo::getStoreId, storeDo.getId())
                    .in(PlatformOrderDo::getId, platformOrderIds)
                    .in(PlatformOrderDo::getStatus, StaticDict.Platform_Order_Status.Zero.getValue(), StaticDict.Platform_Order_Status.Two.getValue(), StaticDict.Platform_Order_Status.Five.getValue())
                    .set(PlatformOrderDo::getStatus, StaticDict.Platform_Order_Status.Four.getValue())
                    .set(PlatformOrderDo::getCancelWay, 0)
                    .set(PlatformOrderDo::getCancelTime, new Date())
            );
            rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_CancelForBound, JSON.toJSONString(new PlatformOrderCancelReq(storeDo.getId(), orderNos)));
        }
        redisTemplate.opsForZSet().add(RedisKeyConstants.orderSyncTimeSet_ClaimInfo_Qoo10 + req.getClaimStat() +"_" + customer, storeDo.getId(), currency - 60 * 1000);
        return null;
    }


    @Override
    public Qoo10ApiRes getOrderByOrderNo(String orderNo, Long storeId) {
        PlatformStoreDo storeDo = platformStoreDao.selectOne(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getId, storeId));
        if (storeDo == null) {
            return new Qoo10ApiRes(500, "店铺对应平台Token未绑定");
        }
        String body = this.getShippingAndClaimInfoByOrderNo_V2(storeDo, orderNo);
        if (StringUtils.isBlank(body)) {
            return new Qoo10ApiRes(500, "Qoo10根据订单号同步订单连接超时");
        }
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return new Qoo10ApiRes(500, "Qoo100根据订单号同步订单失败,JSON body null");
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            return new Qoo10ApiRes(500, "Qoo100根据订单号同步订单失败：" + ErrorCode + "(" + ErrorMsg + ")");
        }
        String ResultObject = JSONObject.parseObject(body).getString("ResultObject");
        String ResultMsg = JSONObject.parseObject(body).getString("ResultMsg");

        if (StringUtils.isBlank(ResultObject)) {
            return new Qoo10ApiRes(500, "Qoo100根据订单号同步订单失败:" + ResultMsg);
        }
        List<OrderQoo10Entity> list = JSON.parseArray(ResultObject, OrderQoo10Entity.class);
        return new Qoo10ApiRes(200, null, list);
    }


    public String getShippingAndClaimInfoByOrderNo_V2(PlatformStoreDo storeDo, String orderNo) {
        if (storeDo == null || StringUtils.isBlank(storeDo.getSellerId())) {
            return ("店铺对应平台Token未绑定");
        }

        String accessToken = this.getQoo10Token(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            return "accessToken 获取失败";
        }
        String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ShippingBasic.GetShippingAndClaimInfoByOrderNo_V2" +
                "&key=" + accessToken +
                "&OrderNo=" + orderNo;

        String body = Qoo10Utils.okHttpRequestGet(url);
        return body;
    }



    @Override
    public void consumerUpdate(RakutenOrderUpdateConReq req) {
        for (PlatformOrderDo orderDo : req.getEts()) {
            platformOrderDao.updateById(orderDo);
        }
        //子表处理
        List<Long> orderIds = req.getProducts().stream().map(PlatformOrderProductDo::getOrderId).distinct().collect(Collectors.toList());
        if (orderIds.isEmpty()) {
            return;
        }
        //匹配系统sku
//        platformOrderService.matchSystemSku(req.getProducts(), req.getStoreId(), req.getCompanyId(), req.getTenantId());
//        platformOrderProductDao.delete(new LambdaQueryWrapper<PlatformOrderProductDo>()
//                .in(PlatformOrderProductDo::getOrderId, orderIds));
//        platformOrderProductDao.insertPlatformOrderItems(req.getProducts());
    }

    @Override
    public void makeShip(Qoo10MarkShipConsumerReq req, Long userId) {
        Map<String, List<Qoo10RequestReq>> basketMap = req.getMarks().stream().collect(Collectors.groupingBy(Qoo10RequestReq::getBasketId));

        List<List<Qoo10RequestReq>> partition = this.splitIntoBatches(basketMap, 499);// 同一购物车的不能分开标发
//        List<List<Qoo10RequestReq>> partition = ListUtil.partition(req.getMarks(), 499);
        for (List<Qoo10RequestReq> qoo10RequestReqs : partition) {
            String msg = this.makeShipPost(new Qoo10MarkShipConsumerReq(req.getStoreId(), qoo10RequestReqs, userId));
            if (StringUtils.isNotBlank(msg)) {
                //全部失败 参数错误等原因
                platformOrderService.updateMarkStatus(req.getMarks().stream().map(Qoo10RequestReq::getId).collect(Collectors.toList()), 2, msg);
            }
        }
    }

    /**
     * 将Map按值分组并分割成多个批次，确保同一键的值在同一批次
     * @param map 源Map
     * @param maxBatchSize 每个批次的最大记录数
     * @return 批次列表
     */
    private <K, V> List<List<V>> splitIntoBatches(Map<K, List<V>> map, int maxBatchSize) {
        List<List<V>> batches = new ArrayList<>();
        List<V> currentBatch = new ArrayList<>();
        int currentBatchSize = 0;

        // 遍历每个basketId对应的列表
        for (List<V> items : map.values()) {
            int itemsSize = items.size();

            // 如果当前项加入会导致批次超过最大容量，则创建新批次
            if (currentBatchSize + itemsSize > maxBatchSize) {
                if (!currentBatch.isEmpty()) {
                    batches.add(currentBatch);
                    currentBatch = new ArrayList<>();
                    currentBatchSize = 0;
                }

                // 如果单个basketId的大小超过最大容量，需要特殊处理
                if (itemsSize > maxBatchSize) {
//                    splitOversizedItems(items, maxBatchSize, batches);
                    continue;
                }
            }
            // 将当前basketId的所有项添加到当前批次
            currentBatch.addAll(items);
            currentBatchSize += itemsSize;
        }
        // 添加最后一个批次（如果不为空）
        if (!currentBatch.isEmpty()) {
            batches.add(currentBatch);
        }
        return batches;
    }


    /**
     * 标发 回传单号
     */
    public String makeShipPost(Qoo10MarkShipConsumerReq req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null || storeDo.getAuthSyncStatus() == null || storeDo.getAuthSyncStatus() == 4) {
            return "店铺密钥过期";
        }
        List<Map<String, String>> shipping = new ArrayList<>();
        for (Qoo10RequestReq mark : req.getMarks()) {
            if (StringUtils.isBlank(mark.getTrackingNo())) {
                continue;
            }
            Map<String, String> ship = new HashMap<>();
            ship.put("OrderNo", mark.getOrderNo());
            ship.put("ShippingCorp", this.getDeliveryCompany(mark));
            ship.put("TrackingNo", mark.getTrackingNo().replaceAll("-", "").trim());
            shipping.add(ship);
        }
        //每次最多500条
        Map<Long, String> trackNoMap = req.getMarks().stream().collect(Collectors.toMap(Qoo10RequestReq::getId, Qoo10RequestReq::getTrackingNo, (v1, v2) -> v1));
        Map<String, Object> param =  new HashMap<>();
        param.put("ShippingInfoJson", JSON.toJSONString(shipping));
        param.put("ReturnType", "application/json");
//        log.error("qoo10标发开始，参数：" + JSON.toJSONString(param));
        String url = Qoo10Utils.QOO_BASE_URL + "/ShippingBasic.SetSendingInfoBulk";
        String accessToken = this.getQoo10Token(storeDo);
        if (StringUtils.isBlank(accessToken)) {
            return "Qoo10 token获取失败";
        }
        String body = Qoo10Utils.okHttpRequestPost(url, accessToken, param);
//        log.error("qoo10标发结束，返回：" + body);
        String msg = "";
        if (StringUtils.isBlank(body)) {
            //连接超时
            msg = "Q0010 标发远程连接超时";
            return msg;
        }
        JSONObject object = JSONObject.parseObject(body);
        //情况1(参数格式不对)：{"ErrorCode":500,"ErrorMsg":"[Internal Server Error] Invalid Type : Parameter Name [ShippingInfoJson] is System.String"}
        //情况2(参数不对)：{"ResultObject":[],"ResultCode":-10007,"ResultMsg":"Non available order."}
        //{"ResultObject":[{"contr_no":1058539132,"result_cd":-10101,"transc_nm":null}],"ResultCode":0,"ResultMsg":"SUCCESS"}
        //{"ResultObject":[{"contr_no":1015974339,"result_cd":0,"transc_nm":"哈哈哈"},{"contr_no":1016068511,"result_cd":0,"transc_nm":"ヤマト宅急便"}],"ResultCode":0,"ResultMsg":"SUCCESS"}
        if (StringUtils.isNotBlank(object.getString("ErrorCode"))) {//错误的情况
            return object.getString("ErrorCode")+":" + object.getString("ErrorMsg");
        }
        String ResultCode = object.getString("ResultCode");
        if (!"0".equals(ResultCode)) {
            return object.getString("ResultCode")+":" + object.getString("ResultMsg");
        }
        List<Qoo10MarkResponse> responses = JSONArray.parseArray(object.getString("ResultObject"), Qoo10MarkResponse.class);
//        List<String> contrNo = responses.stream().filter(i -> !"0".equals(i.getContr_no()) && "0".equals(i.getResult_cd())).map(Qoo10MarkResponse::getContr_no).distinct().collect(Collectors.toList());
//        List<Long> successId = req.getMarks().stream().filter(i -> contrNo.contains(i.getOrderNo())).map(Qoo10RequestReq::getId).collect(Collectors.toList());
        List<Long> successId = new ArrayList<>();
        Map<String, Long> idMap = req.getMarks().stream().collect(Collectors.toMap(Qoo10RequestReq::getOrderNo, Qoo10RequestReq::getId, (v1, v2) -> v1));
        Map<String, List<Long>> failMap = new HashMap<>();
        for (Qoo10MarkResponse respons : responses) {
            Long orderId = idMap.get(respons.getContr_no());
            if (orderId == null) {
                continue;
            }
            if (!"0".equals(respons.getContr_no()) && "0".equals(respons.getResult_cd())) {
                //成功
                successId.add(orderId);
            }
            else {
                failMap.computeIfAbsent(respons.getResult_cd(), k -> new ArrayList<>()).add(orderId);
            }
        }
//        List<Long> failId = req.getMarks().stream().filter(i -> !contrNo.contains(i.getOrderNo())).map(Qoo10RequestReq::getId).collect(Collectors.toList());
        List<OperateRecordDo> operateRecordDos = new ArrayList<>();
        if (!successId.isEmpty()) {
            platformOrderService.updateMarkStatus(successId, 3, null);
            for (Long orderId : successId) {
                OperateRecordDo operateRecordDo = new OperateRecordDo(orderId, OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip, null, new Date(), trackNoMap.get(orderId));
                operateRecordDos.add(operateRecordDo);
            }
        }
        if (!failMap.isEmpty()) {
            Map<String, String> makeshipErrorCodeMap = this.createMakeshipErrorCodeMap();
            for (String failCode : failMap.keySet()) {
                String failReason = makeshipErrorCodeMap.getOrDefault(failCode, failCode);
                platformOrderService.updateMarkStatus(failMap.get(failCode), 2, failReason);
                for (Long orderId : failMap.get(failCode)) {
                    OperateRecordDo operateRecordDo = new OperateRecordDo(orderId, OperateTypeEnum.PlatformOrder.getValue(), SysConstant.platformOrder_MarkShip_Fail, null, new Date(), failReason);
                    operateRecordDos.add(operateRecordDo);
                }
            }

        }
        if(!operateRecordDos.isEmpty()) {
            List<List<OperateRecordDo>> partition = ListUtil.partition(operateRecordDos, 3000);
            for (List<OperateRecordDo> partList : partition) {
                rabbitTemplate.convertAndSend(RabbitQueueConstant.CrossMall_CMOrder_OperateList, JSON.toJSONString(partList));
            }
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformOrder_Auto_SendMail, JSON.toJSONString(new SendMailConsumerReq(2, req.getStoreId(), successId)));
        return null;
    }


    public  Map<String, String> createMakeshipErrorCodeMap() {
        Map<String, String> errorCodeMap = new HashMap<>();
        errorCodeMap.put("0", "Success");
        errorCodeMap.put("-10000", "Please check the Seller Authorization Key.");
        errorCodeMap.put("-10001", "Order Number format error");
        errorCodeMap.put("-10002", "Expects parameter ShippingCorp, which was not supplied.");
        errorCodeMap.put("-10003", "Expects parameter TrackingNo, which was not supplied.");
        errorCodeMap.put("-10004", "There is not OrdNo for Seller");
        errorCodeMap.put("-10005", "Cust.Number format error");
        errorCodeMap.put("-10006", "Json string form is invalid.");
        errorCodeMap.put("-10007", "Non available order");
        errorCodeMap.put("-10010", "Failed to update shipping info.");
        errorCodeMap.put("-10011", "Over limit count. Available under");
        errorCodeMap.put("-10101", "This order is being claimed.");
        errorCodeMap.put("-10102", "Can not update shipping-stat at visit-delivery.");
        errorCodeMap.put("-10103", "Tracking No is used before.");
        errorCodeMap.put("-10104", "Please enter the tracking number.");
        errorCodeMap.put("-10105", "Please check the size of a tracking number.");
        errorCodeMap.put("-10106", "Please use a valid tracking number. (Front)");
        errorCodeMap.put("-10107", "Please use a valid tracking number. (Rear)");
        errorCodeMap.put("-10108", "Tracking No is not valid. (Check digit)");
        errorCodeMap.put("-10109", "Orders from China to Japan cannot be sent to the unregistered courier. For related inquiries,Qoo10 Support");
        errorCodeMap.put("-10111", "Tracking number is invalid. (You should confirm shipment with the number through printing AWB.)");
        errorCodeMap.put("-10112", "No authority to update shipping status with other delivery company.");
        errorCodeMap.put("-10113", "This tracking number is already used.");
        errorCodeMap.put("-10114", "This tracking number is already used.");
        errorCodeMap.put("-10115", "OrderNo format error");
        errorCodeMap.put("-10116", "Expects parameter ShippingCorp, which was not supplied.");
        errorCodeMap.put("-10117", "Expects parameter TrackingNo, which was not supplied.");
        errorCodeMap.put("-10118", "Please use correct delivery company. Shipping Methods are not matched between buyer selected and you");
        errorCodeMap.put("-10119", "No authority to update shipping status with JP Post delivery company");
        errorCodeMap.put("-10120", "Shipment processing failed. Please enter the exact name of the delivery company.");
        errorCodeMap.put("-10121", "Shipment processing failed.Please choose courier company that matches shipping country.");
        errorCodeMap.put("-10122", "There is not OrdNo for Seller");
        errorCodeMap.put("-90001", "The API does not exist.");
        errorCodeMap.put("-90002", "You are not authorized for this.");
        errorCodeMap.put("-90003", "You are not authorized for this.");
        errorCodeMap.put("-90004", "Seller authorization key is expired. Use a new key.");
        errorCodeMap.put("-90005", "Seller authorization key is expired. Use a new key.");
        return errorCodeMap;
    }


    public String getDeliveryCompany(Qoo10RequestReq mark) {
        String shippingCorp = mark.getShippingCorp();
        //佐川急便（佐川）
        //ヤマト宅急便（黑猫）
        //ネコポス(黑猫小包)
        //ゆうパケット(黑猫盒子box)
        if ("Sagawa".equals(mark.getShippingCorp())) {
            shippingCorp = "佐川急便";
        } else if ("Yamato".equals(mark.getShippingCorp())) {
            if ("yamato_one".equals(mark.getChannelCode()) || "yamato_more".equals(mark.getChannelCode())) {
                shippingCorp = "ネコポス";
            } else if ("yamato_zhai".equals(mark.getChannelCode())) {
                shippingCorp = "ヤマト宅急便";
            } else if ("uamato_box".equals(mark.getChannelCode())) {
                shippingCorp = "ゆうパケット";
            }
        } else if ("yamato_one".equals(mark.getShippingCorp()) || "yamato_more".equals(mark.getShippingCorp())) {
            shippingCorp = "ネコポス";
        } else if ("yamato_zhai".equals(mark.getShippingCorp())) {
            shippingCorp = "ヤマト宅急便";
        } else if ("uamato_box".equals(mark.getShippingCorp())) {
            shippingCorp = "ゆうパケット";
        }
        return shippingCorp;
    }


    @Override
    public void getAllGoodsInfo() {
        List<PlatformStoreDo> storeDoList = platformStoreDao.selectList(new LambdaQueryWrapper<PlatformStoreDo>().eq(PlatformStoreDo::getPlatformCode, StaticDict.Store_PlatformCode.Qoo10.getValue())
                .eq(PlatformStoreDo::getAuthSyncStatus, 1).isNotNull(PlatformStoreDo::getAppSecret));
        storeDoList.forEach(storeDo -> {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Qoo10, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, null, null)));
        });
    }


    /**
     * 同步平台商品
     */
    @Override
    public String getAllGoodsInfo(PlatformStoreDo storeDo) {
//        this.updateInventoryQtyUnit(storeDo);
//        if (true) {
//            return null;
//        }
        String key = RedisKeyConstants.PlatformProduct_Sync_Flag_ + customer + storeDo.getId();
        Object o = redisTemplate.opsForValue().get(key);
        if (o != null) {
            return storeDo.getStoreCode() + " 正在同步商品";
        }
        redisTemplate.opsForValue().set(key, 1, 10, TimeUnit.MINUTES);
        //ItemStatus 商品の取引状況（承認待ち=S0、販売中止(販売者)=S1、販売中=S2、販売中止(Qoo10)=S3、販売制限(Qoo10)=S5、承認拒否=S8）
        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
        List<Item> items = new ArrayList<>();
        List<String> itemStatusList = Arrays.asList("S2");
//        List<String> itemStatusList = Arrays.asList("S0", "S1", "S2", "S3", "S5", "S8");
        for (String itemStatus : itemStatusList) {
            int page = 1;
            int totalPage = 1;
            do {
                String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ItemsLookup.GetAllGoodsInfo" +
                        "&ItemStatus=" + itemStatus +
                        "&key=" + accessToken +
                        "&Page=" + page;
                String body = Qoo10Utils.okHttpRequestGet(url);

                if (StringUtils.isBlank(body)) {
                    break;
                }
                JSONObject object = JSONObject.parseObject(body);
                if (object == null) {
                    break;
                }
                String ErrorCode = object.getString("ErrorCode");
                String ErrorMsg = object.getString("ErrorMsg");
                if (StringUtils.isNotBlank(ErrorCode)) {
                    log.error("qoo10 同步商品错误(获取父sku列表)：" + ErrorCode + ":" + ErrorMsg);
                    break;
                }
                String resultObjectStr = JSONObject.parseObject(body).getString("ResultObject");
                if (StringUtils.isBlank(resultObjectStr)) {
                    break;
                }
                ResultObject result = JSON.parseObject(resultObjectStr, ResultObject.class);
                totalPage = result.getTotalPages();
                if (result.getItems() != null) {
                    items.addAll(result.getItems());
                }
                page++;
            } while (page <= totalPage);
        }
        //全量同步时 根据管理番号去删除
        if (!items.isEmpty()) {
            List<String> parentSkuList = items.stream().map(Item::getSellerCode).collect(Collectors.toList());
            LambdaQueryWrapper<PlatformProductDo> selectWrapper = new LambdaQueryWrapper<>();
            selectWrapper.select(PlatformProductDo::getId);
            selectWrapper.notIn(PlatformProductDo::getParentSku, parentSkuList);
            selectWrapper.eq(PlatformProductDo::getCompanyId, storeDo.getCompanyId());
            selectWrapper.eq(PlatformProductDo::getStoreId, storeDo.getId());
            List<PlatformProductDo> deleteDoList = platformProductService.getBaseMapper().selectList(selectWrapper);
            List<Long> ids = deleteDoList.stream().map(PlatformProductDo::getId).collect(Collectors.toList());
            if (!ids.isEmpty()) {
                LambdaUpdateWrapper<PlatformProductDo> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.in(PlatformProductDo::getId, ids);
                updateWrapper.set(PlatformProductDo::getDeleteFlag, 1);
                updateWrapper.set(PlatformProductDo::getDeleteBy, -2);
                updateWrapper.set(PlatformProductDo::getDeleteTime, new Date());
                platformProductService.update(updateWrapper);
            }
        }
        //这里的SellerCode 是 管理番号
        for (Item item : items) {
            //rabbitmq 去处理
            rabbitTemplate.convertAndSend(RabbitQueueConstant.GetPlatformProduct_Qoo10_ParentSku, JSON.toJSONString(new ItemUpdateConsumerReq(storeDo, item.getSellerCode(), null)));
        }
        redisTemplate.delete(key);
        return null;
    }


    /**
     * 通过sellerCode 获取 platformSku 再去维护 父sku
     * @param storeDo
     * @param sellerCode
     * @param itemCode
     */
    @Override
    public void getGoodsInventoryInfo(PlatformStoreDo storeDo, String sellerCode, String itemCode) {
        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
        String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ItemsLookup.GetGoodsInventoryInfo" +
                "&key=" + accessToken +
//                "&ItemCode=" + "888266910" +
                "&SellerCode=" + sellerCode;//mskkf40
        String body = Qoo10Utils.okHttpRequestGet(url);

        if (StringUtils.isBlank(body)) {
            return;
        }
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return;
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            log.error("qoo10 ItemsLookup.GetGoodsInventoryInfo：" + ErrorCode + ":" + ErrorMsg);
            return;
        }
        String resultObjectStr = JSONObject.parseObject(body).getString("ResultObject");
        if (StringUtils.isBlank(resultObjectStr)) {
            return;
        }
        List<GoodsInventoryInfoEntity> entityList = JSON.parseArray(resultObjectStr, GoodsInventoryInfoEntity.class);
        List<PlatformProductDo> orderDos = new ArrayList<>();
        int index = 0;
        for (GoodsInventoryInfoEntity item : entityList) {
            if (StringUtils.isBlank(item.getItemTypeCode())) {
                continue;
            }
            PlatformProductDo productDo = new PlatformProductDo();
            productDo.setStoreId(storeDo.getId());
            productDo.setCompanyId(storeDo.getCompanyId());
            productDo.setTenantId(storeDo.getTenantId());
            productDo.setParentSku(sellerCode);
            productDo.setHideItem(0);
            productDo.setItemName("");
            productDo.setPlatformSku(item.getItemTypeCode());
            productDo.setOptionName1(item.getName1());
            productDo.setOptionName2(item.getName2());
            productDo.setOptionName3(item.getName3());
            productDo.setOptionValue1(item.getValue1());
            productDo.setOptionValue2(item.getValue2());
            productDo.setOptionValue3(item.getValue3());
            productDo.setOptionHorizontalSeq(String.valueOf(index));
            productDo.setPrice(item.getPrice());
            orderDos.add(productDo);
            index++;
        }
        boolean delete = true;
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformProduct_Rakuten_UpdateByParentSKu, JSON.toJSONString(new PlatformProductSyncReq(orderDos,
                StaticDict.Store_PlatformCode.Rakuten.getValue(), delete, storeDo.getId(), storeDo.getCompanyId())));
//        List<String> platformSkuList = entityList.stream().map(GoodsInventoryInfoEntity::getItemTypeCode).filter(StringUtils::isNotBlank).collect(Collectors.toList());
//        if (CollUtil.isEmpty(platformSkuList)) {
//            return;
//        }
        //维护管理番号
//        platformProductService.update(new LambdaUpdateWrapper<PlatformProductDo>()
//                .eq(PlatformProductDo::getStoreId, storeDo.getId())
//                .in(PlatformProductDo::getPlatformSku, platformSkuList)
//                        .and(i -> i.eq(PlatformProductDo::getParentSku, "").or().isNull(PlatformProductDo::getParentSku))
//                .set(PlatformProductDo::getParentSku, sellerCode));
    }



    public String updateInventoryQtyUnit(PlatformStoreDo storeDo) {
        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());

        //mskxh51  973588884
        String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ItemsOptions.UpdateInventoryQtyUnit" +
                "&key=" + accessToken +
                "&ItemCode=" + "973588884" +
                "&SellerCode=" + "mskxh51" +
                "&OptionName=" + "カラー" +
                "&OptionValue=" + "ミントブルー" +
                "&OptionCode=" + "mskxh51lblx" +
                "&Qty=" + "2500";
        String body = Qoo10Utils.okHttpRequestGet(url);

        if (StringUtils.isBlank(body)) {
            return "qoo10 UpdateInventoryQtyUnit：连接超时";
        }
        //method=ItemsOptions.UpdateInventoryQtyUnit : {"ResultCode":0,"ResultMsg":"Success"}
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return "qoo10 UpdateInventoryQtyUnit：JSON 转义失败";
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            log.error("qoo10 UpdateInventoryQtyUnit：" + ErrorCode + ":" + ErrorMsg);
            return ErrorCode + ":" + ErrorMsg;
        }
        Integer resultObject = object.getInteger("ResultCode");
        if (resultObject != 0) {
            return resultObject + "";
        }
        return null;
    }

    /**
     * Qoo10に登録した商品の単一型オプション情報を照会するためのAPIメソッドです。
     *
     * @param storeDo
     * @param sellerCode
     */
    public void getGoodsOptionInfo(PlatformStoreDo storeDo, String sellerCode) {
        StringBuilder inventoryInfo =    new StringBuilder();
        inventoryInfo.append("カラー||*スカイグレー||*サイズ||*フリー||").append("*0||*").append(200).append("||*").append("mskkf40skgk");

        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
        String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ItemsLookup.GetGoodsOptionInfo" +
                "&key=" + accessToken +
//                "&ItemCode=" + "1142913316" +
                "&SellerCode=" + "mskkf40";

        String body = Qoo10Utils.okHttpRequestGet(url);

        if (StringUtils.isBlank(body)) {
            return;
        }
        //method=ItemsOptions.EditGoodsInventory : {"ResultCode":0,"ResultMsg":"Success"}
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return;
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            log.error("qoo10 同步商品错误(获取sku)：" + ErrorCode + ":" + ErrorMsg);
            return;
        }
        String resultObjectStr = object.getString("ResultObject");
        if (StringUtils.isBlank(resultObjectStr)) {
            return;
        }
        JSONArray resultObject = object.getJSONArray("ResultObject");
        for (int i = 0; i < resultObject.size(); i++) {
            JSONObject jsonObject = resultObject.getJSONObject(i);
            String Name = jsonObject.getString("Name");
            String Value = jsonObject.getString("Value");
            String OptionCode = jsonObject.getString("OptionCode");
            String Price = jsonObject.getString("Price");
        }
    }

    public String editGoodsInventory(PlatformStoreDo storeDo, String sellerCode, String inventoryInfo) {
        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
//        String url = Qoo10Utils.QOO_BASE_URL + "?v=1.0&" + "&returnType=json&method=ItemsOptions.EditGoodsInventory" +
//                "&key=" + accessToken +
////                "&ItemCode=" + "1142913316" +
//                "&SellerCode=" + sellerCode +
//                "&InventoryInfo=" + inventoryInfo;
//        String body = Qoo10Utils.okHttpRequestGet(url);

        Map<String, Object> param = new HashMap<>();
        param.put("SellerCode", sellerCode);
        param.put("InventoryInfo", inventoryInfo);
        param.put("ReturnType", "application/json");
        String body = Qoo10Utils.okHttpRequestPost(Qoo10Utils.QOO_BASE_URL + "/ItemsOptions.EditGoodsInventory", accessToken, param);

        if (StringUtils.isBlank(body)) {
            return "qoo10 EditGoodsInventory：" + "连接超时";
        }
        //method=ItemsOptions.EditGoodsInventory : {"ResultCode":0,"ResultMsg":"Success"}
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return "qoo10 EditGoodsInventory：" + "JSON转义失败";
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            log.error("qoo10 EditGoodsInventory：" + ErrorCode + ":" + ErrorMsg);
            return ErrorCode + ":" + ErrorMsg;
        }

        Integer resultObject = object.getInteger("ResultCode");
        if (resultObject != 0) {
            return resultObject + "";
        }
        return null;
    }


    @Override
    public void setStockByStoreId(StockToPlatformConsumerReq req) {
        PlatformStoreDo storeDo = platformStoreDao.selectById(req.getStoreId());
        if (storeDo == null) {
            return;
        }
        AsyncJobDo asyncJobDo = asyncJobDao.selectById(req.getJobId());
        if (asyncJobDo == null) {
            return;
        }
        //告诉他正在处理
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), 1, 0, null)));
        List<PlatformSkuStockDto> skuStockList = productStockDao.getPlatformSkuStockList(Arrays.asList(StaticDict.Store_PlatformCode.Qoo10.getValue()),
                null, req.getParentSKuList(), req.getInventoryLink(), Arrays.asList(req.getStoreId()));
        //qoo10 不支持单个sku回传 要一整个parentSKU回传，不然会把其他sku 删除
        if (skuStockList.isEmpty()) {
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Finish, JSON.toJSONString(new AsyncFinishConsumerReq(req.getJobId(), null)));
            return;
        }
        Map<String, List<PlatformSkuStockDto>> parentSkuMap = skuStockList.stream().filter(skuStock -> StringUtils.isNotBlank(skuStock.getParentSku())).collect(Collectors.groupingBy(PlatformSkuStockDto::getParentSku));
        List<InventoryQoo10Req> inventoryList = new ArrayList<>();
        List<SetGoodsPriceQtyBulkReq> bulkReqList = new ArrayList<>();
        Map<String, Integer> qtyMap = new HashMap<>();
        String stockRedisKey = RedisKeyConstants.PLATFORMSTOCK_KEY_PREFIX +customer +"_"+ req.getStoreId();
        Map<Long, Integer> small20IdToQuantityMap = new HashMap<>();
        parentSku:
        for (String parentSku : parentSkuMap.keySet()) {
            if (StringUtils.isBlank(parentSku)) {
                continue;
            }
            List<PlatformSkuStockDto> skuList = parentSkuMap.get(parentSku);
            //判断是不是没有变体的sku  此类商品需要调其他api
            if (skuList.size() == 1 && Objects.equals(skuList.get(0).getPlatformSku(), skuList.get(0).getParentSku())) {
                PlatformSkuStockDto skuStock = skuList.get(0);
                double stockPercent = skuStock.getStockPercent() < 0 || skuStock.getStockPercent() > 1 ? 0.95 : 1 - skuStock.getStockPercent();
                int quantity = (int) ((double) skuStock.getLeftQty() / skuStock.getQty() * stockPercent);
                quantity = Math.min(Math.max(quantity, 0), 99999);
                if (quantity > 0 && quantity <= 20) {
                    small20IdToQuantityMap.put(skuStock.getId(), quantity); // 保存ID与库存的映射
                }
                if (quantity <= 20 && req.getUserId() == null) {
                    quantity = 0;
                }
                Integer lastQuantity = platformOrderService.getLastRecordedInventory(stockRedisKey, skuStock.getPlatformSku());
                if (lastQuantity != null && lastQuantity.equals(quantity) && req.getUserId() == null) {
                    //自动回传 且 和上次回传数量一致
                    continue;
                }
                bulkReqList.add(new SetGoodsPriceQtyBulkReq(skuStock.getPlatformSku(), String.valueOf(quantity)));
                continue;
            }
            //组合商品库存回传组装
            boolean allSame = true;
            Map<String, Integer> skuQtyMap = new HashMap<>();
            for (PlatformSkuStockDto skuStock : skuList) {
                if (StringUtils.isBlank(skuStock.getOptionHorizontalSeq()) || skuStock.getPrice() == null) {
                    //没有顺序 没有售价信息
                    continue parentSku;
                }
                double stockPercent = skuStock.getStockPercent() < 0 || skuStock.getStockPercent() > 1 ? 0.95 : 1 - skuStock.getStockPercent();
                int quantity = (int) ((double) skuStock.getLeftQty() / skuStock.getQty() * stockPercent);
                quantity = Math.min(Math.max(quantity, 0), 99999);
                if (quantity > 0 && quantity <= 20) {
                    small20IdToQuantityMap.put(skuStock.getId(), quantity); // 保存ID与库存的映射
                }
                if (quantity <= 20 && req.getUserId() == null) {
                    quantity = 0;
                }
                Integer lastQuantity = platformOrderService.getLastRecordedInventory(stockRedisKey, skuStock.getPlatformSku());
                if (lastQuantity == null || !lastQuantity.equals(quantity)) {
                    allSame = false;
                }
                skuQtyMap.put(skuStock.getPlatformSku(), quantity);
            }
            if (allSame && req.getUserId() == null) {//管理番号下 平台回传数量和上一次全部一致 则不用回传
                continue;
            }
            StringBuilder inventoryInfo = new StringBuilder();
            skuList.sort(Comparator.nullsLast(Comparator.comparingInt(o -> StringUtils.isNotBlank(o.getOptionHorizontalSeq()) ? Integer.parseInt(o.getOptionHorizontalSeq()) : 0)));
            for (PlatformSkuStockDto skuStock : skuList) {
                Integer quantity = skuQtyMap.get(skuStock.getPlatformSku());
                if (quantity == null) {
                    quantity = 0;
                }
                if (inventoryInfo.length() > 0) {
                    inventoryInfo.append("$$");
                }
                inventoryInfo.append(skuStock.getOptionName1()).append("||*").append(skuStock.getOptionValue1());
                if (StringUtils.isNotBlank(skuStock.getOptionName2()) && StringUtils.isNotBlank(skuStock.getOptionValue2())) {
                    inventoryInfo.append("||*").append(skuStock.getOptionName2()).append("||*").append(skuStock.getOptionValue2());
                }
                if (StringUtils.isNotBlank(skuStock.getOptionName3()) && StringUtils.isNotBlank(skuStock.getOptionValue3())) {
                    inventoryInfo.append("||*").append(skuStock.getOptionName3()).append("||*").append(skuStock.getOptionValue3());
                }
                //价格 库存 sku
                inventoryInfo.append("||*").append(skuStock.getPrice()).append("||*").append(quantity).append("||*").append(skuStock.getPlatformSku());
                qtyMap.put(skuStock.getPlatformSku(), quantity);
            }
            inventoryList.add(new InventoryQoo10Req(parentSku, inventoryInfo.toString()));
        }
        try {
            String key = asyncJobDo.getJobType() + "_count_" + "_" + asyncJobDo.getCompanyId() + "_" + customer + "_" + DateUtils.dateFormatToString(new Date(), "yyyyMMdd");
            long count = redisTemplate.opsForValue().increment(key, 1);
            redisTemplate.expire(key, 60 * 60 * 25, TimeUnit.SECONDS);
            String fileName = asyncJobDo.getJobName() + "_" + count + ".csv";
            String tempFilePath = omsFilePath + fileName;
            CsvExportParams csvParam = new CsvExportParams();
//            csvParam.setEncoding("Shift-JIS");
            csvParam.setEncoding("UTF-8");
            csvParam.setTextMark("");
            CsvUtils.initCsv(tempFilePath, csvParam, StockToPlatformRecordVo.class);
            Map<String, String> thisStockMap = new HashMap<>();
            //组合商品库存回传开始
            for (InventoryQoo10Req qoo10Req : inventoryList) {
                String error = null;
                try {
                    error = this.editGoodsInventory(storeDo, qoo10Req.getParentSku(), qoo10Req.getInventoryInfo());
                } catch (Exception e) {
                    e.printStackTrace();
                    error = e.getMessage();
                }
//                log.error("qoo10 editGoodsInventory:" + qoo10Req.getParentSku() + ":" + error);
                List<StockToPlatformRecordVo> errorList = new ArrayList<>();
                for (PlatformSkuStockDto inventoryRakutenEntity : parentSkuMap.get(qoo10Req.getParentSku())) {
                    if (StringUtils.isBlank(error) && StringUtils.isNotBlank(inventoryRakutenEntity.getParentSku())) {
                        //成功
                        errorList.add(new StockToPlatformRecordVo(inventoryRakutenEntity.getParentSku(), inventoryRakutenEntity.getPlatformSku(), qtyMap.get(inventoryRakutenEntity.getPlatformSku()), "成功", null));
                        thisStockMap.put(inventoryRakutenEntity.getPlatformSku(), String.valueOf(qtyMap.get(inventoryRakutenEntity.getPlatformSku())));

                    } else {
                        errorList.add(new StockToPlatformRecordVo(inventoryRakutenEntity.getParentSku(), inventoryRakutenEntity.getPlatformSku(), inventoryRakutenEntity.getQty(), "失败", error));
                    }
                }
                CsvUtils.appendToCsv(tempFilePath, errorList);
                rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), null, errorList.size(), null)));
            }
            //不是组合商品库存回传 开始
            List<StockToPlatformRecordVo> errorList = new ArrayList<>();
            for (SetGoodsPriceQtyBulkReq bulkReq : bulkReqList) {
                String error = this.setGoodsPriceQty(storeDo, bulkReq);
                if (StringUtils.isBlank(error)) {
                    //成功
                    errorList.add(new StockToPlatformRecordVo(bulkReq.getSellerCode(), bulkReq.getSellerCode(), Integer.parseInt(bulkReq.getQty()), "成功", null));
                    thisStockMap.put(bulkReq.getSellerCode(), bulkReq.getQty());
                }
                else {
                    errorList.add(new StockToPlatformRecordVo(bulkReq.getSellerCode(), bulkReq.getSellerCode(), Integer.parseInt(bulkReq.getQty()), "失败", error));
                }
            }
            if (!errorList.isEmpty()) {
                CsvUtils.appendToCsv(tempFilePath, errorList);
                rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), null, errorList.size(), null)));
            }

            if (!thisStockMap.isEmpty() && req.getUserId() == null) {
                //记录本次回传数量至redis
                redisTemplate.opsForHash().putAll(stockRedisKey, thisStockMap);
//                redisTemplate.expire(stockRedisKey, 8, TimeUnit.HOURS);
            }
            //本机文件传到oms上
            String objectNameTemporary = "";
            if (filePath.startsWith("http")) {
                try {
                    objectNameTemporary = AliOss.temporaryFile2(fileName, new File(tempFilePath));
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("导出文件失败" + e.getMessage());
                }
            }
            //文件路径
            String path = fileUrl + objectNameTemporary;
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Finish, JSON.toJSONString(new AsyncFinishConsumerReq(req.getJobId(), path)));
        } catch (Exception e) {
            e.printStackTrace();
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(req.getJobId(), 4, 0, e.getMessage())));
        }
        //用ZSet处理低库存SKU的存储与对比
        rabbitTemplate.convertAndSend(RabbitQueueConstant.PlatformProduct_InventoryLess, JSON.toJSONString(new UpdateInventoryLessReq(req.getStoreId(), req.getUserId(), small20IdToQuantityMap)));
    }




    public String setGoodsPriceQty(PlatformStoreDo storeDo, SetGoodsPriceQtyBulkReq req) {
        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
        Map<String, Object> param = new HashMap<>();
        param.put("SellerCode", req.getSellerCode());
        param.put("Qty", req.getQty());
        param.put("ReturnType", "application/json");
        String body = Qoo10Utils.okHttpRequestPost(Qoo10Utils.QOO_BASE_URL + "/ItemsOrder.SetGoodsPriceQty", accessToken, param);

        if (StringUtils.isBlank(body)) {
            return "qoo10 SetGoodsPriceQty：" + "连接超时";
        }
        //method=ItemsOptions.EditGoodsInventory : {"ResultCode":0,"ResultMsg":"Success"}
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return "qoo10 SetGoodsPriceQty：" + "JSON转义失败";
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            log.error("qoo10 SetGoodsPriceQty：" + ErrorCode + ":" + ErrorMsg);
            return ErrorCode + ":" + ErrorMsg;
        }

        Integer resultObject = object.getInteger("ResultCode");
        if (resultObject != 0) {
            return resultObject + "";
        }
        return null;
    }


    //为了变更为配送准备的状态API方法。（您可以请求多个订单，一个请求最多500个）
    @Override
    public String setSellerCheckYN_V2(List<SetSellerCheckYNTimeReq> reqList, PlatformStoreDo storeDo) {
        if (CollUtil.isEmpty(reqList) || reqList.size() > 500) {
            return null;
        }

        List<SetSellerCheckYNReq> entityList = new ArrayList<>();
        for (SetSellerCheckYNTimeReq timeReq : reqList) {
            LocalDate localDate = this.calculateDeliveryDate(timeReq.getPayTime(), 2);
            if (localDate != null) {
                String yyyyMMdd = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                entityList.add(new SetSellerCheckYNReq(timeReq.getOrderNo(), yyyyMMdd, "1", ""));
            }
        }
        if (entityList.isEmpty()) {
            return null;
        }
        String accessToken = Qoo10Utils.getQoo10Token(storeDo.getSellerId(), storeDo.getAppKey(), storeDo.getAppSecret());
        Map<String, Object> param = new HashMap<>();
        param.put("SendPlanDtInfoJson", JSON.toJSONString(entityList));
        param.put("ReturnType", "application/json");
        String body = Qoo10Utils.okHttpRequestPost(Qoo10Utils.QOO_BASE_URL + "/ShippingBasic.SetSellerCheckYNBulk", accessToken, param);

        if (StringUtils.isBlank(body)) {
            return "qoo10 SetSellerCheckYNBulk：" + "连接超时";
        }
        JSONObject object = JSONObject.parseObject(body);
        if (object == null) {
            return "qoo10 SetSellerCheckYNBulk：" + "JSON转义失败";
        }
        String ErrorCode = object.getString("ErrorCode");
        String ErrorMsg = object.getString("ErrorMsg");
        if (StringUtils.isNotBlank(ErrorCode)) {
            log.error("qoo10 SetSellerCheckYNBulk：" + ErrorCode + ":" + ErrorMsg);
            return ErrorCode + ":" + ErrorMsg;
        }

        Integer resultObject = object.getInteger("ResultCode");
        if (resultObject != 0) {
            return resultObject + "";
        }
        return null;
    }
}

